# coding:utf-8
import json
import urllib
import random
import time
from datetime import datetime, date, timedelta

from flask import request, current_app
from flask_restful import Api, Resource

from app import db
from app.api.constant import PACK_SET_INFO
from app.api.pay_codes import DISCOUNT_LIMIT
from app.api.pay_schemas import half_price_schema
from app.api_v2.pay_schemas import wx_pay_schema, price_pack_set_schema
from app.api_v2.codes import PACK_SET_NOT_EXIST
from app.api.supplier_codes import NOT_ENGINEER
from app.op.models import (
    Bill, User, Partic, BidCostRecord, Pack, Area,
    PricePackSet, BidUserQueue)
from common.constant import BidQueueStatus, MEMBERS_PHONE
from common.wechat_util import wx_mobile_pay_client, wx_mobile_order_api
from app.api.codes import PARAMS_ILLEGAL, Code, SUCCESS
from app.op.constant import UserType, BillChnl, BillType, BillSubType, BillStatus, BidCostType, \
    ParticStatus
from .views import AppAuthResource, Response

api = Api()


@api.resource('/pack_set')
class PackSetResource(Resource):
    """
    created by chenhj at 2017/12/4

    """
    def get(self):
        price_pack_set = PricePackSet.get_list_by_args(deleted_at=0)
        price_data = price_pack_set_schema.dump(price_pack_set)[0]

        return Response(SUCCESS, {
            'price_pack_set': price_data,
            'discount_pack_set': PACK_SET_INFO
        })


@api.resource('/pay/wx/app')
class WxPayResource(AppAuthResource):
    """
    created by chenhj at 2017/8/15

    """
    def post(self):
        # 不是工程商则直接返回
        if self.user.type != UserType.ENGINEER.value:
            return Response(NOT_ENGINEER)

        data, errors = wx_pay_schema.load(request.get_json())
        if errors:
            return Response(PARAMS_ILLEGAL.new_format_msg(list(errors.values())[0][0]))
        pack_set = PricePackSet.get_by_id(data['set_id'])
        if not pack_set:
            return Response(PACK_SET_NOT_EXIST)

        now = datetime.fromtimestamp(time.time())
        out_trade_no = '{0}{1}{2}{3}'.format(
            self.user.id,
            wx_mobile_order_api.mch_id,
            now.strftime('%Y%m%d%H%M%S'),
            random.randint(1000, 10000)
        )[:32]

        pay_fee = int(pack_set.price * 100)
        if self.user.mobile in MEMBERS_PHONE:
            pay_fee = 1

        prepay_data = wx_mobile_order_api.create(
            'APP', '¥{}元套餐'.format(pack_set.price), pay_fee,
            urllib.parse.urljoin(request.url_root, 'api/v2/pay/wx/app/notify'),
            out_trade_no=out_trade_no, client_ip=request.remote_addr
        )
        if prepay_data['return_code'] != 'SUCCESS':
            # 统一下单失败, 直接返回错误信息
            return Response(Code(prepay_data['return_code'], prepay_data['return_msg']))

        if prepay_data['result_code'] != 'SUCCESS':
            # 交易失败, 返回错误信息
            return Response(Code(prepay_data['err_code'], prepay_data['err_code_des']))

        Bill.create(
            uid=self.user.id,
            chnl=BillChnl.WEPAY.value,
            chnl_code=out_trade_no,
            type=BillType.INCOMING.value,
            sub_type=BillSubType.BUY_PACK.value,
            item=data['set_id'],
            amt=pack_set.price,
            bid_point=pack_set.bid_point + pack_set.gift_bid_point,
            sms_point=0,
            status=BillStatus.TO_BE_PAY.value,
            desc='账户充值'
        )
        return Response(SUCCESS, {
            'wxpay': wx_mobile_order_api.get_appapi_params(prepay_data['prepay_id'])
        })


@api.resource('/pay/wx/app/discount')
class WxPayDiscountResource(AppAuthResource):
    """
    alter by zhouhl 2018-01-25
    将此接口修改为1000汇币以上9折优惠

    create by ld_wu 2017-10-30
    老用户五折优惠，截止时间2017-12-31
    """
    def post(self):

        # 不是工程商则直接返回
        if self.user.type != UserType.ENGINEER.value:
            return Response(NOT_ENGINEER)

        data, errors = half_price_schema.load(request.get_json())
        if errors:
            return Response(PARAMS_ILLEGAL.new_format_msg(list(errors.values())[0][0]))
        bid_point = data['bid_point']

        now = datetime.fromtimestamp(time.time())
        out_trade_no = '{0}{1}{2}{3}'.format(
            self.user.id,
            wx_mobile_order_api.mch_id,
            now.strftime('%Y%m%d%H%M%S'),
            random.randint(1000, 10000)
        )[:32]

        # 购买1000汇币以内不享受优惠
        if bid_point < 1000:
            return Response(DISCOUNT_LIMIT)

        # 95折购买汇币，结果向下取整
        fee = int(bid_point * 0.95)
        pay_fee = fee * 100

        if self.user.mobile in MEMBERS_PHONE:
            pay_fee = 1

        prepay_data = wx_mobile_order_api.create(
            'APP', '九五折优惠', pay_fee,
            urllib.parse.urljoin(request.url_root, 'api/v2/pay/wx/app/notify'),
            out_trade_no=out_trade_no, client_ip=request.remote_addr
        )
        if prepay_data['return_code'] != 'SUCCESS':
            # 统一下单失败, 直接返回错误信息
            return Response(Code(prepay_data['return_code'], prepay_data['return_msg']))

        if prepay_data['result_code'] != 'SUCCESS':
            # 交易失败, 返回错误信息
            return Response(Code(prepay_data['err_code'], prepay_data['err_code_des']))

        Bill.create(
            uid=self.user.id,
            chnl=BillChnl.WEPAY.value,
            chnl_code=out_trade_no,
            type=BillType.INCOMING.value,
            sub_type=BillSubType.HALF_PACK.value,
            amt=fee,
            bid_point=bid_point,
            sms_point=0,
            status=BillStatus.TO_BE_PAY.value,
            desc='九五折优惠充值'
        )
        return Response(SUCCESS, {
            'wxpay': wx_mobile_order_api.get_appapi_params(prepay_data['prepay_id'])
        })


@api.resource('/pay/wx/app/notify')
class WxpayNotifyResource(Resource):
    """
    created by chenhj at 2017/8/16

    """
    def post(self):
        """
        created by chenhj at 2017/8/16

        """
        # 这里只需要直接返回SUCCESS的字符串给微信即可
        from flask import Response
        data = wx_mobile_pay_client.parse_payment_result(request.data)

        demand_ids = []
        if data['return_code'] == 'SUCCESS' and data['result_code'] == 'SUCCESS':
            # 支付成功
            out_trade_no = data['out_trade_no']
            bill = Bill.get_by_args(chnl_code=out_trade_no)
            if bill and bill.status == BillStatus.TO_BE_PAY.value:
                bill.status = BillStatus.PAID.value
                user = User.get_by_id(bill.uid)

                # 已有套餐, 直接更新
                if user.pack:
                    user.pack.bid_point += bill.bid_point
                    user.pack.accum_bid_point += bill.bid_point

                    # 有效期为购买日期起+366天(来自南向)
                    today = date.today()
                    if (user.pack.end_date - today).days < 366:
                        user.pack.end_date = today + timedelta(days=366)

                    left_bid_point = user.pack.bid_point
                # 没有套餐, 新建套餐
                else:
                    user.attention_areas = Area.get_list_by_ids(
                        Area.get_city_ids(user.prov)
                    ).all()
                    Pack.create(
                        uid=user.id,
                        accum_bid_point=bill.bid_point,
                        bid_point=bill.bid_point,
                    )
                    left_bid_point = bill.bid_point
                BidCostRecord.create(
                    user_id=user.id,
                    cost_type=BidCostType.PAY.value,
                    bid_point=bill.bid_point,
                    left_bid_point=left_bid_point
                )
                current_app.zone_stat_exchanger.exchange_send(json.dumps({
                    'sales': float(bill.amt),
                    'pay_user_id': user.id,
                    'war_zone_id': user.war_zone_id
                }))
                current_app.common_producer.send(
                    json.dumps(
                        dict(
                            backend='bid_stock_stat',
                            func='day_stat',
                            kwargs=dict(
                                stat_type='incoming',
                                stat_cnt=bill.bid_point,
                            )
                        )
                    )
                )
                # 如果该用户有待付费订单, 则扣取, 并更新该参与状态
                to_pay_partics = Partic.query.filter_by(
                    supplier_id=user.id,
                    status=ParticStatus.BALANCE_NOT_ENOUGH.value,
                    deleted_at=0
                ).order_by(
                    Partic.id
                )
                for each_partic in to_pay_partics:
                    if user.pack.bid_point >= each_partic.offer:
                        user.pack.bid_point -= each_partic.offer
                        each_partic.status = ParticStatus.NOT_CONTACT.value
                        BidCostRecord.create(
                            user_id=user.id,
                            cost_type=BidCostType.BID.value,
                            bid_point=each_partic.offer,
                            left_bid_point=user.pack.bid_point,
                            demand_id=each_partic.demand_id
                        )
                        demand_ids.append(each_partic.demand_id)
                        # 修改外呼队列状态
                        queue = BidUserQueue.query.filter(
                            BidUserQueue.partic_id == each_partic.id,
                            BidUserQueue.status == BidQueueStatus.RECHARGE
                        ).first()
                        if queue:
                            queue.status = BidQueueStatus.WAITING

                        current_app.zone_stat_exchanger.exchange_send(json.dumps({
                            'cost_bid_point': float(each_partic.offer),
                            'cost_bid_user_id': user.id,
                            'war_zone_id': user.war_zone_id
                        }))
                        current_app.common_producer.send(
                            json.dumps(
                                dict(
                                    backend='bid_stock_stat',
                                    func='day_stat',
                                    kwargs=dict(
                                        stat_type='cost_bid_point',
                                        stat_cnt=int(each_partic.offer),
                                    )
                                )
                            )
                        )

        if demand_ids:
            db.session.commit()
            for each_demand_id in demand_ids:
                Partic.clear_demand_partic_cache_data(current_app.redis, each_demand_id)
        return Response('SUCCESS')
